﻿using System;
using System.Collections.Generic;
using System.Web;
using System.Net.Mail;
using System.Net;

namespace GlobalTracker.WebService.Core
{
  /// <summary>
  /// Esta classe é responsável pelo envio de e-mails de alerta para os responsáveis por cada dispositivo móvel
  /// que ultrapassar os limites de uma cerca eletrônica.
  /// 
  /// Ela foi criada para satisfazer diretamente os casos de uso:
  /// - M09: Obter coordenadas geográficas
  /// </summary>
  public class EMail
  {

    private bool access; // Variável que determina se houve sucesso na autenticação com o servidor.
    private bool hasAuthentication; // Variável que determina se é necessário fazer uma autenticação explicita.
    private bool enableSSL; // Variável que determina se utilizará SSL.
    private MailMessage message; // Variável que define o objeto de e-mail, contendo assunto, mensagem, etc...
    private SmtpClient smtpClient; // Objeto para acesso ao servidor de SMTP. 
    private NetworkCredential networkCredential; // Objeto de autenticação para envio do e-mail.

    /// <summary>
    /// Construtor.
    /// </summary>
    public EMail()
    {
      access = true;
      message = new MailMessage();
      smtpClient = new SmtpClient();
      networkCredential = new NetworkCredential();
    }

    /// <summary>
    /// Propriedade que retorna se houve sucesso na autenticação.
    /// </summary>
    public bool Access
    {
      get
      {
        return access;
      }
      set
      {
        access = value;
      }
    }

    /// <summary>
    /// Propriedade utilizada para determinar o uso do SSL.
    /// </summary>
    public bool EnableSSL
    {
      get { return enableSSL; }
      set { enableSSL = value; }
    }

    /// <summary>
    /// Propriedade utilizada para determinar se haverá autenticação ou não.
    /// </summary>
    public bool HasAuthentication
    {
      get { return hasAuthentication; }
      set { hasAuthentication = value; }
    }

    /// <summary>
    /// Define o e-mail de origem
    /// </summary>
    /// <param name="mail"></param>
    public void SetFrom(string mail)
    {
      try
      {
        message.From = new MailAddress(mail);
      }
      catch
      {
        if (access)
        {          
          access = false;
          return;
        }
      }
    }

    /// <summary>
    /// Define e-mails de destino.
    /// </summary>
    /// <param name="mails"></param>
    public void SetTo(string mails)
    {
      try
      {
        message.To.Clear();
        mails.Replace(" ", "");
        int i = 0;
        while (i < mails.Length)
        {
          if (mails[i] == ';')
          {
            string temp = mails.Substring(0, i);
            message.To.Add(temp);
            mails = mails.Remove(0, i + 1);
            i = 0;
          }
          else
            if (i == mails.Length - 1)
            {
              string temp = mails.Substring(0, i + 1);
              message.To.Add(temp);
              mails = mails.Remove(0, i + 1);
              i = 0;
            }
            else
              i++;
        }
      }
      catch
      {
        if (access)
        {
          access = false;
          return;
        }
      }
    }

    /// <summary>
    /// Define e-mails de cópia.
    /// </summary>
    /// <param name="mails"></param>
    public void SetCC(string mails)
    {
      try
      {
        message.CC.Clear();
        mails.Replace(" ", "");
        int i = 0;
        while (i < mails.Length)
        {
          if (mails[i] == ';')
          {
            message.CC.Add(mails.Substring(0, i));
            mails = mails.Remove(0, i + 1);
            i = 0;
          }
          else
            if (i == mails.Length - 1)
            {
              message.CC.Add(mails.Substring(0, i + 1));
              mails = mails.Remove(0, i + 1);
              i = 0;
            }
            else
              i++;
        }
      }
      catch
      {
        if (access)
        {
          access = false;
          return;
        }
      }
    }

    /// <summary>
    /// Método para envio de e-mail.
    /// </summary>
    public void SendMail()
    {
      try
      {
        message.IsBodyHtml = true;
        smtpClient.EnableSsl = enableSSL;

        if (hasAuthentication)
        {
          smtpClient.Credentials = networkCredential;
          smtpClient.Send(message);
        }
        else
        {
          smtpClient.Send(message);
        }
      }
      catch (SmtpFailedRecipientException sfre)
      {
        access = false;
        throw new Exception("Verifique as permissões de acesso ao servidor ou nome do usuário e senha.\r\n" + sfre.Message);
      }
      catch (SmtpException se)
      {
        access = false;
        throw new Exception("Erro ao enviar e-mail, verifique as configurações do servidor SMTP e a porta.\r\n" + se.Message);
      }
      catch (Exception exp)
      {
        throw new Exception(exp.Message);
      }
    }

    /// <summary>
    /// Método para envio de e-mail.
    /// </summary>
    /// <param name="subject">Assunto do e-mail</param>
    /// <param name="body">Mensagem do e-mail</param>
    /// <param name="from">Endereço de origem do e-mail</param>
    /// <param name="to">Endereço de destino do e-mail</param>
    /// <param name="smtpServer">Servidor de SMTP utilizado para o envio do e-mail</param>
    /// <param name="port">Porta utilizada para o envio do e-mail</param>
    /// <param name="userName">Usuário para autenticaçao no servidor de SMTP</param>
    /// <param name="password">Senha para autenticaçao no servidor de SMTP</param>
    /// <returns>Retorna true se obteve sucesso no envio e false caso não.</returns>
    public bool SendMail(string subject, string body, string from, string to, string smtpServer, string port, string userName, string password)
    {
      networkCredential.UserName = userName;
      networkCredential.Password = password;
      return this.SendMail(subject, body, from, to, smtpServer, port);
    }


    /// <summary>
    /// Método para envio de e-mail.
    /// </summary>
    /// <param name="subject">Assunto do e-mail</param>
    /// <param name="body">Mensagem do e-mail</param>
    /// <param name="from">Endereço de origem do e-mail</param>
    /// <param name="to">Endereço de destino do e-mail</param>
    /// <param name="smtpServer">Servidor de SMTP utilizado para o envio do e-mail</param>
    /// <param name="port">Porta utilizada para o envio do e-mail</param>
    /// <returns>Retorna true se obteve sucesso no envio e false caso não.</returns>
    public bool SendMail(string subject, string body, string from, string to, string smtpServer, string port)
    {
      bool send = true;

      try
      {
        message.Subject = subject;
        message.Body = body;
        SetFrom(from);
        SetTo(to);

        smtpClient.Host = smtpServer;
        smtpClient.Port = Convert.ToInt32(port);
        SendMail();
      }
      catch (Exception exp)
      {
        if (access)
        {
          if (smtpServer == "" || port == "")
            throw new Exception("Deve se informar o servidor SMTP e a porta!");
          else
            throw new Exception(exp.Message);

          access = false;
          send = false;
        }
      }
      return send;
    }
  }
}